﻿using BCCommon;
using BCCommon.Enums;
using BCCommon.PaymentEnums;
using BCCommon.TMS.RedPacket;
using BCData.TMS.AgentWallet;
using BCData.TMS.RedPacket.RedPacket;
using BCData.TMS.RedPacket.RedPacketSupplement;
using BCDto.Sim.Admin.Admin;
using BCDto.TMS.RedPacket.RedPacket;
using BCDto.TMS.RedPacket.RedPacket.RedPacketRequest;
using BCDto.TMS.RedPacket.RedPacketStatistics;
using BCEntity.Common.EntityNameConst;
using BCEntity.TMS.RedPacket.RedPacketSupplement;
using BCService.TMS.AgentWallet;
using BCService.Utils;
using System;
using System.Collections.Generic;

namespace BCService.TMS.RedPacket.RedPacket
{
    public class RedPacketService : IRedPacketService
    {
        private readonly IRedPacketData redPacketData;
        private readonly IRedisService redisService;
        private readonly IDatabaseContext databaseContext;
        private readonly IRedPacketSupplementData redPacketSupplementData;
        private readonly IAgentWalletService agentWalletService;
        private readonly string key = string.Format("{0}", EntityNameConst.RedPacketEntity);
        private readonly string keyRedPacketSupplementEntity = string.Format("{0}", EntityNameConst.RedPacketSupplementEntity);
        public RedPacketService(
            IRedPacketData redPacketData,
            IRedisService redisService,
            IDatabaseContext databaseContext,
            IRedPacketSupplementData redPacketSupplementData,
            IAgentWalletService agentWalletService)
        {
            this.redPacketData = redPacketData;
            this.redisService = redisService;
            this.databaseContext = databaseContext;
            this.redPacketSupplementData = redPacketSupplementData;
            this.agentWalletService = agentWalletService;
        }

        public RedPacketDto Create(long redPacketId, RedPacketRequestDto requestDto, AdminDto admin)
        {
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException(" 用户验证失败,错误操作 ");
            }
            var entity = redPacketData.GetSingle(redPacketId).Result;
            if (entity == null)
            {
                throw new ArgumentException(" 当前红包类型不存在,不可补充 ");
            }
            if (entity.AgentRecordId != admin.AgentRecord.AgentRecordId)
            {
                throw new ArgumentException(" 不可操作别人的红包 ");
            }
            var amount = requestDto.RedPackCount * entity.RedPacketAmount;
            string orderNo = Guid.NewGuid().ToString();
           
            entity.RedPackCount += requestDto.RedPackCount;
            entity.RemainCount += requestDto.RedPackCount;
            entity.UpdateTime = DateTime.Now;
            entity.EditAdminId = admin.AdminId;
            entity.EditAdminName = admin.FullName;
            this.databaseContext.BeginTransaction();
            agentWalletService.Pay(admin, amount, "红包补充", FlowType.RedPacket, PaymentChannelType.Balance,
               FlowDirectionType.Outlay, orderNo);
            var result = this.redPacketData.UpdateAsync(entity).GetAwaiter().GetResult();
            var redPacketSupplementEntity = new RedPacketSupplementEntity
            {
                RedPacketId = entity.RedPacketId,
                RedPacketTypeId = entity.RedPacketTypeId,
                RedPacketAmount = entity.RedPacketAmount,
                RedPacketCount = requestDto.RedPackCount,
                RedPacketName = entity.RedPacketName,
                RedPacketType = entity.RedPacketType,
                AgentRecordId = entity.AgentRecordId,
                CreateTime = DateTime.Now,
                CreateAdminId = admin.AdminId,
                CreateAdminName = admin.FullName,
            };
            this.redPacketSupplementData.InsertAsync(redPacketSupplementEntity).GetAwaiter().GetResult();
            this.databaseContext.Commit();
            this.redisService.DeleteMultipleKey(key, false);
            this.redisService.DeleteMultipleKey(keyRedPacketSupplementEntity, false);
            return result.As<RedPacketDto>();
        }

        public RedPacketDto GetSingle(long redPacketId)
        {
            string cacheKey = this.redisService.GetKey(key, redPacketId);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var result = this.redPacketData.GetSingle(redPacketId).GetAwaiter().GetResult();
                if (result == null)
                {
                    throw new ArgumentException(" 获取红包失败 ");
                }
                return result.As<RedPacketDto>();
            }, TimeSpan.FromDays(1));
            return resultRedis;
        }

        public IEnumerable<RedPacketDto> GetList(bool? isEnabled, AdminDto admin)
        {
            long agentRecordId = admin.AgentRecord.AgentRecordId;
            string cacheKey = this.redisService.GetKey(key, isEnabled, agentRecordId);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var result = this.redPacketData.GetList(isEnabled, agentRecordId).Result;
                return result.As<IEnumerable<RedPacketDto>>();
            }, TimeSpan.FromDays(1));
            return resultRedis;

        }

        public PageableList<RedPacketDto> Query(bool? isEnabled, int pageIndex, int pageSize)
        {
            string cacheKey = this.redisService.GetKey(key, isEnabled, pageIndex, pageSize);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var (list, dataCount) = this.redPacketData.Query(isEnabled, pageIndex, pageSize).GetAwaiter().GetResult();
                var result = new PageableList<RedPacketDto>
                {
                    Count = dataCount,
                    Items = list.As<IEnumerable<RedPacketDto>>(),
                    PageIndex = pageIndex,
                    PageSize = pageSize,
                    ServerTime = DateTime.Now,
                };
                return result;
            }, TimeSpan.FromDays(1));
            return resultRedis;

        }

        public RedPacketCountDto GetRedPacketCount(AdminDto admin)
        {
            string cacheKey = this.redisService.GetKey(key,admin.AgentRecord.AgentRecordId);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var result = this.redPacketData.GetRedPacketCount(admin.AgentRecord.AgentRecordId).Result;
                return result.As<RedPacketCountDto>();
            }, TimeSpan.FromDays(1));
            return resultRedis;


        }

        public bool Disabled(long redPacketId, AdminDto admin)
        {
            var entity = this.redPacketData.GetSingle(redPacketId).GetAwaiter().GetResult();
            if (entity == null)
            {
                throw new ArgumentException(" 获取红包失败 ");
            }
            if (entity.AgentRecordId != admin.AgentRecord.AgentRecordId)
            {
                throw new ArgumentException(" 不可操作别人的红包 ");
            }
            entity.Enabled = false;
            entity.UpdateTime = DateTime.Now;
            entity.EditAdminId = admin.AdminId;
            entity.EditAdminName = admin.FullName;
            var result = this.redPacketData.UpdateAsync(entity).GetAwaiter().GetResult();
            this.redisService.DeleteMultipleKey(key, false);
            return result != null;
        }

        public bool Enabled(long redPacketId, AdminDto admin)
        {
            var entity = this.redPacketData.GetSingle(redPacketId).GetAwaiter().GetResult();
            if (entity == null)
            {
                throw new ArgumentException(" 获取红包失败 ");
            }
            if (entity.AgentRecordId != admin.AgentRecord.AgentRecordId)
            {
                throw new ArgumentException(" 不可操作别人的红包 ");
            }
            entity.Enabled = true;
            entity.UpdateTime = DateTime.Now;
            entity.EditAdminId = admin.AdminId;
            entity.EditAdminName = admin.FullName;
            var result = this.redPacketData.UpdateAsync(entity).GetAwaiter().GetResult();
            this.redisService.DeleteMultipleKey(key, false);
            return result != null;
        }
        public RedPacketAgentStatisticsDto GetRedPacketAgentStatistics(AdminDto admin, GrundlagenTypeEnum? grundlagenType)
        {
            var entity = this.redPacketData.GetRedPacketAgentStatistics(admin.AgentRecord.AgentRecordId, grundlagenType).Result;
            var result = entity.As<RedPacketAgentStatisticsDto>();
            result.ReceiveCountPercent = Compare.GetRate(result.ReceiveCount, result.AllCount);
            result.RemainCountPercent = Compare.GetRate(result.RemainCount, result.AllCount);
            result.ReceiveAmountPercent = Compare.GetRate(result.ReceiveAmount, result.AllAmount);
            result.RemainAmountPercent = Compare.GetRate(result.RemainAmount, result.AllAmount);
            return result;
        }

    }
}
